package com.apitest.utils;

import com.apitest.moudle.Attributes;
import com.apitest.moudle.CaseDesign;

import java.util.ArrayList;
import java.util.List;

/**
 * @program: APITest
 * @description:
 * @author: shixing
 * @create: 2021-05-05 09:52
 **/
public class Descartes {
    /**
     * 计算 多个集合的笛卡尔积
     *
     * @param dimValues ArrayList<CaseDesign>
     * @return ArrayList<ArrayList < Attributes>>
     */
    public static ArrayList<ArrayList<Attributes>> parse(ArrayList<CaseDesign> dimValues) {
        ArrayList<ArrayList<Attributes>> result = new ArrayList<>();

        for (int i = 0; i < dimValues.size(); i++) {
            List<Attributes> curList = dimValues.get(i).getAttributsParmasAll();
            //首个集合，直接放输入到结果集中
            if (0 == i) {
                for (Attributes tempStr : curList) {
                    ArrayList<Attributes> newlist = new ArrayList<>();
                    newlist.add(tempStr);
                    result.add(newlist);
                }
                continue;
            }
            //将前一个集合的乘积 result，自我复制 curListCount 份，并将当前集合的元素追加到上边
            selfCopy(result, curList);
        }
        /**
         * caseParing(result)  用例结对
         * removeRepetition 根据结对算法，阐述重复结对的用例。
         */
        return removeRepetition(result, caseParing(result));
    }

    /**
     * 根据当前的集合，将之前的结果集复制
     *
     * @param result  　　之前的集合相称的结果集
     * @param curList 　　当前集合
     */
    private static void selfCopy(List<ArrayList<Attributes>> result, List<Attributes> curList) {
        List<ArrayList<Attributes>> tempList = new ArrayList<>();
        for (Attributes strOfCurList : curList) {
            for (ArrayList<Attributes> strOfResult : result) {
                // 重新开辟一块内存，储存case
                ArrayList<Attributes> ofres = new ArrayList<>();
                ofres.addAll(strOfResult);
                ofres.add(strOfCurList);
                tempList.add(ofres);
            }
        }
        result.clear();
        for (ArrayList<Attributes> templ : tempList) {
            result.add(templ);
        }
    }

    /**
     * Pairing
     *
     * @param result descartes
     * @return
     */
    private static ArrayList<ArrayList<ArrayList<Attributes>>> caseParing(List<ArrayList<Attributes>> result) {
        ArrayList pairingAll = new ArrayList();
        result.forEach(atts -> {
            ArrayList pairingList = new ArrayList();
            atts.forEach(at -> {
                int index = atts.indexOf(at) + 1;
                for (int i = index; i < atts.size(); i++) {
                    ArrayList pairing = new ArrayList();
                    pairing.add(at);
                    pairing.add(atts.get(i));
                    pairingList.add(pairing);
                }
            });
            pairingAll.add(pairingList);
        });
        return pairingAll;
    }

    /**
     * @param result  用例
     * @param pairing 用例结对
     */
    private static ArrayList<ArrayList<Attributes>> removeRepetition(ArrayList<ArrayList<Attributes>> result, ArrayList<ArrayList<ArrayList<Attributes>>> pairing) {
        // 新的case存放
        System.out.println("pairing before result size :"+ result.size());
        ArrayList<ArrayList<Attributes>> caseList = new ArrayList<>();
        ArrayList<ArrayList<ArrayList<Attributes>>> newPairing = new ArrayList<>();
        newPairing.addAll(pairing);
        for (int len = result.size() - 1; len > 0; len--) {
            //用例
            ArrayList<Attributes> cases = result.get(len);
            //用例对应的结对数据
            ArrayList<ArrayList<Attributes>> parisList = newPairing.get(len);
            int amount = 0;
            int index = 0;
            for (int i = 0; i < parisList.size(); i++) {
                for (int j = pairing.size() - 1; j >= 0; j--) {
                    ArrayList<Attributes> parisObj = parisList.get(i);
                    ArrayList<Attributes> comObj = pairing.get(j).get(i);
                    boolean ins = arrEquals(comObj, parisObj);
                    if (len != j && ins) {
                        amount++;
                        index = j;
                        break;
                    }
                }
            }
            if (amount == parisList.size()) {
                pairing.remove(index);
            }else {
                caseList.add(cases);
            }
        }
        result.clear();
        System.out.println("pairing after result size :"+ caseList.size());
        return caseList;
    }

    /**
     * Equals
     *
     * @param attrs
     * @param pairs
     * @return
     */
    private static boolean arrEquals(ArrayList<Attributes> attrs, ArrayList<Attributes> pairs) {
        return objEquals(attrs.get(0), pairs.get(0)) && objEquals(attrs.get(1), pairs.get(1));
    }
    private static boolean objEquals(Attributes attr, Attributes pair) {
        return attr.getName().equals(pair.getName()) &&
                attr.getData().equals(pair.getData()) &&
                attr.getValid().equals(pair.getValid());
    }
}
